package com.dashen.sso.server.config.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.sql.DataSource;
import java.util.Collections;

/**
 * @author Barry Wang
 */
@Configuration
//工具方法，
//用来在当前应用context里(必须是一个DispatcherServlet context)
// 开启一个授权server(例如AuthorizationEndpoint)和一个TokenEndpoint。
//server的多个属性可以通过自定义AuthorizationServerConfigurer类型
//(如AuthorizationServerConfigurerAdapter的扩展)的Bean来定制。
//通过正常使用spring security的特色EnableWebSecurity，用户负责保证授权Endpoint(/oauth/authorize)的安全，
//但Token Endpoint(/oauth/token)将自动使用http basic的客户端凭证来保证安全。
//通过一个或者多个AuthorizationServerConfigurer提供一个ClientDetailService来注册client(必须)。
@EnableAuthorizationServer
public class DaShenAuthorizationServerConfigurerAdapter extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    public DaShenAuthorizationServerConfigurerAdapter(){

    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        /* 配置token获取合验证时的策略 */
        //security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");

        //允许表单认证
        //security.allowFormAuthenticationForClients();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 配置oauth2的 client信息
//        clients.inMemory()
//                .withClient("sso-client")
//                .secret(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("sso-client-secret"))
//                .scopes("user-info")
//                .authorizedGrantTypes("authorization_code", "refresh_token","password", "implicit")
//                .redirectUris("http://dashena.com/sso-client/login/oauth2/code/dashen"
//                            ,"https://dashena.com/sso-client/login/oauth2/code/dashen"
//                            ,"http://localhost:9010/sso-client/login/oauth2/code/dashen")
//                .autoApprove(true)
//        ;

        clients.jdbc(dataSource).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints
                // table oauth_access_token
                .tokenStore(tokenStore())
                // table oauth_code
                .authorizationCodeServices(authorizationCodeServices())
                //.approvalStore()
                ;

        //endpoints;

    }

    @Bean
    public AuthorizationCodeServices authorizationCodeServices(){
        return new JdbcAuthorizationCodeServices(dataSource);
    }

    @Bean
    public TokenStore tokenStore(){
        return new JdbcTokenStore(dataSource);
    }

    @Bean("userDetailsService")
    public UserDetailsService userDetailsService(){
        return new DaShenUserDetailsServiceImpl();
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setUserDetailsService(userDetailsService());
        provider.setPasswordEncoder(PasswordEncoderFactories.createDelegatingPasswordEncoder());
        return new ProviderManager(Collections.singletonList(provider));
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    public static void main(String[] args){
        String  rst = PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("sso-client-secret");
        System.out.println(rst);
    }
}
